
vsf_title = Vemma Signature Fix
vsf_ver = 0.7.1

#NoTrayIcon
#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.
#SingleInstance force
;~ SetBatchLines -1
vsf_fulltitle = %vsf_title% %vsf_ver%
vsf_psloggedonpath = C:\PSTools\PSLoggedOn.exe

;~ If !A_IsAdmin
;~ {
	;~ MsgBox, 16, %vsf_fulltitle%, %vsf_title% must be run as Administrator.
	;~ ExitApp
;~ }

IfNotExist, %vsf_psloggedonpath%
{
	MsgBox, 16, %vsf_fulltitle%, %vsf_psloggedonpath% not found.
	ExitApp
}


Gui, Add, Text, x2 y5 w90 h20 , Computer name:
Gui, Add, Edit, x80 y5 w228 h20 vvsf_nameinput, 
Gui, Add, Button, x307 y5 w70 h20 Default vvsf_searchbutton gvsf_search, Search
Gui, Add, Edit, x-3 y35 w380 h190 vvsf_log ReadOnly HWNDEdit_ID, 
Gui, Add, Text, x2 y230 w50 h20 Disabled vvsf_sigtextlabel, Signature:
Gui, Add, DropDownList, x52 y230 w110 h100 Disabled vvsf_sigdropdown gvsf_choosesig hwndDDL_ID,
Gui, Add, Edit, x182 y230 w120 h20 Disabled vvsf_mailtobox, 
Gui, Add, Button, x302 y230 w70 h20 Disabled vvsf_updatebutton gvsf_updatesig, Update
; Generated using SmartGUI Creator for SciTE
Gui, Show, w380 h260, %vsf_fulltitle%


;~ Gui, Add, Text, x2 y10 w90 h20 , Computer name:
;~ Gui, Add, Edit, x82 y10 w230 h20 vvsf_nameinput, 
;~ Gui, Add, Button, x312 y10 w70 h20 +Default vvsf_searchbutton gvsf_search, Search
;~ Gui, Add, Edit, x2 y40 w380 h190 vvsf_log ReadOnly HWNDEdit_ID, 
;~ ; Generated using SmartGUI Creator for SciTE
;~ Gui, Show, w386 h236, %vsf_fulltitle%
return
;######################################
;######################################
;########## END OF AUTOEXEC ###########
;######################################
;######################################
Esc::
	gosub, ClearVars
	gosub, Reset
	vsf_notfirstrun =
	GuiControl, Focus, vsf_nameinput
return

;DEBUG
if !A_IsCompiled
{
	F9::
	if vsf_sigpath
		Run, explorer.exe %vsf_sigpath%
	return
	F10::ListVars
}

GuiClose:
ExitApp

;######################################
;######################################
;############ SUBROUTINES #############
;######################################
;######################################

vsf_search:
	gosub, DisableButtons
	gosub, ClearVars
	GuiControlGet, vsf_computername,,vsf_nameinput
	if !vsf_computername
		return
	
	if vsf_notfirstrun
		AddStatus("----------",2)
	StringUpper, vsf_computername, vsf_computername
	
	AddStatus("Checking for " . vsf_computername . "...")
		RunWait, %comspec% /c ping %vsf_computername% -4 -n 1 -w 500 > %A_Temp%\vsf_ping.txt,,Hide
		if ErrorLevel
		{
			AddStatus(">> ERROR: " . vsf_computername . " not found on network.",2)
			gosub, EnableButtons
			return
		} else {
			Loop, read, %A_Temp%\vsf_ping.txt
			{
				IfInString, A_LoopReadLine, Pinging
				{
					StringSplit, vsf_pingresult, A_LoopReadLine, %A_Space%, []
					vsf_ip = %vsf_pingresult3%
				}
			}
			AddStatus("> Found: " . vsf_ip)
		}
	
	AddStatus("Verifying administrative share access to " . vsf_computername . "...")
		IfNotExist, \\%vsf_computername%\c$
		{
			AddStatus("ERROR: " . vsf_computername . " cannot be accessed.",2)
			gosub, EnableButtons
			return
		} else {
			AddStatus("> Success!")
		}
	
	AddStatus("Detecting logged-in user...")
		vsf_loggedonnextline =
		RunWait, %comspec% /c %vsf_psloggedonpath% \\%vsf_computername% > %A_Temp%\vsf_psloggedon.txt,,Hide
		Loop, read, %A_Temp%\vsf_psloggedon.txt
		{
			if vsf_loggedonnextline
			{
				StringSplit, vsf_psloggedon, A_LoopReadLine, \
				vsf_username = %vsf_psloggedon2%
				AddStatus("> Found: " . vsf_username)
				break
			}
			IfInString, A_LoopReadLine, Users logged on locally
				vsf_loggedonnextline = 1
			IfInString, A_LoopReadLine, Error opening HKEY_USERS for
			{
				AddStatus(">> Alt. Method...")
				gosub, DetectUser_alt
				break
			}
		}
		if vsf_detectfail
		{
			AddStatus(">> ERROR: Cannot detect logged-in user.",2)
			vsf_detectfail =
			gosub, EnableButtons
			return
		}
	
	AddStatus("Detecting signature files...")
		gosub, DetectPath
		if !vsf_sigpath
		{
			AddStatus(">> ERROR: Cannot locate signature path.")
			goto, Completed
		}
		AddStatus("> Found path: " . vsf_sigpath)
		Loop, %vsf_sigpath%\*.htm
			vsf_siglist = %vsf_siglist%%A_LoopFileName%`n
		Sort, vsf_siglist
		StringSplit, vsf_sigs, vsf_siglist, `n
		if vsf_sigs0 = 0
		{
			AddStatus(">> ERROR: No signature files detected.",2)
			gosub, EnableButtons
			return
		}
		AddStatus("> Detected signatures: ",0)
		Loop, %vsf_sigs0%
		{
			if vsf_sigs%A_Index% =
				continue
			StringTrimRight, vsf_sigs%A_Index%, vsf_sigs%A_Index%, 4
			if !vsf_sigs
				vsf_sigs := vsf_sigs%A_Index%
			else
				vsf_sigs := vsf_sigs . "," . vsf_sigs%A_Index%
		}
		AddStatus(vsf_sigs)
		StringReplace, vsf_sigs, vsf_sigs, `,, |, All
		GuiControl,,vsf_sigdropdown, %vsf_sigs%
		gosub, EnableSigChoice
		goto, Completed
return


DetectUser_alt:
	RunWait, %comspec% /c sc \\%vsf_computername% start RemoteRegistry,,Hide
	RunWait, %comspec% /c ping -n 1 -w 2000 -4 localhost,,Hide
	vsf_loggedonnextline =
	RunWait, %comspec% /c %vsf_psloggedonpath% \\%vsf_computername% > %A_Temp%\vsf_psloggedon.txt,,Hide
	Loop, read, %A_Temp%\vsf_psloggedon.txt
	{
		if vsf_loggedonnextline
		{
			RunWait, %comspec% /c sc \\%vsf_computername% stop RemoteRegistry,,Hide
			StringSplit, vsf_psloggedon, A_LoopReadLine, \
			vsf_username = %vsf_psloggedon2%
			AddStatus("> Found: " . vsf_username)
			return
		}
		IfInString, A_LoopReadLine, Users logged on locally
			vsf_loggedonnextline = 1
		IfInString, A_LoopReadLine, Error opening HKEY_USERS for
		{
			vsf_detectfail = 1
			return
		}
	}
return


DetectPath:
	vsf_7path = \\%vsf_computername%\c$\Users\%vsf_username%\AppData\Roaming\Microsoft\Signatures
	IfExist, %vsf_7path%
	{
		vsf_sigpath = %vsf_7path%
		return
	}
	vsf_XPpath = \\%vsf_computername%\c$\Documents and Settings\%vsf_username%\Application Data\Microsoft\Signatures
	IfExist, %vsf_XPpath%
	{
		vsf_sigpath = %vsf_XPpath%
		return
	}
	If vsf_sigpath
	{
		AddStatus("> Found: " . vsf_sigpath)
		return
	} else {
		AddStatus(">> Guessing...")
		;Win7 guess
		StringGetPos, vsf_guesspathpos, vsf_7path, \%vsf_username%\AppData
		StringLeft, vsf_guesspath, vsf_7path, vsf_guesspathpos
		Loop, %vsf_guesspath%\*.*, 2
			vsf_profilelist = %vsf_profilelist%%A_LoopFileTimeModified%`t%A_LoopFileName%`n
		Sort, vsf_profilelist, N R
		StringSplit, vsf_allprofiles, vsf_profilelist, `n
		StringSplit, vsf_profiles, vsf_allprofiles1, %A_Tab%
		IfExist, %vsf_guesspath%\%vsf_profiles2%\AppData\Roaming\Microsoft\Signatures
		{
			vsf_sigpath = %vsf_guesspath%\%vsf_profiles2%\AppData\Roaming\Microsoft\Signatures
			return
		} 
		;WinXP guess
		StringGetPos, vsf_guesspathpos, vsf_XPpath, \%vsf_username%\Application
		StringLeft, vsf_guesspath, vsf_XPpath, vsf_guesspathpos
		Loop, %vsf_guesspath%\*.*, 2
			vsf_profilelist = %vsf_profilelist%%A_LoopFileTimeModified%`t%A_LoopFileName%`n
		Sort, vsf_profilelist, N R
		StringSplit, vsf_allprofiles, vsf_profilelist, `n
		StringSplit, vsf_profiles, vsf_allprofiles1, %A_Tab%
		IfExist, %vsf_guesspath%\%vsf_profiles2%\Application Data\Microsoft\Signatures
		{
			vsf_sigpath = %vsf_guesspath%\%vsf_profiles2%\Application Data\Microsoft\Signatures
			return
		} 
	}
return


vsf_choosesig:
	vsf_mailto = 
	vsf_mailtonameguess =
	GuiControl,, vsf_mailtobox, 
	gosub, DisableSigEdit
	
	GuiControlGet, vsf_sigdropdown
	AddStatus("Analyzing signature file '" . vsf_sigdropdown . "'...")
	vsf_chosensig = %vsf_sigpath%\%vsf_sigdropdown%.htm
	Loop, Read, %vsf_chosensig%
	{
		IfInString, A_LoopReadLine, mailto:
		{
			StringGetPos, vsf_mailtopos, A_LoopReadLine, mailto:
			vsf_mailtopos := vsf_mailtopos + 7 ;compensate for 'mailto:'
			StringTrimLeft, vsf_mailto, A_LoopReadLine, %vsf_mailtopos%
			StringGetPos, vsf_mailtopos, vsf_mailto, .com
			vsf_mailtopos := vsf_mailtopos + 4 ;compensate for the '.com'
			StringLeft, vsf_mailto, vsf_mailto, %vsf_mailtopos%
			AddStatus("> Detected mailto:" . vsf_mailto)
		}
		;Guess what email address should be
		if (vsf_mailto and !vsf_mailtonameguess) 
		{
			IfInString, A_LoopReadLine, </a>
			{
				StringGetPos, vsf_mailtonamepos, A_LoopReadLine, @vemma.com, R1
				vsf_mailtonameposoffset := StrLen(A_LoopReadLine) - vsf_mailtonamepos
				StringGetPos, vsf_mailtonamestartpos, A_LoopReadLine, >, R1, %vsf_mailtonameposoffset%
				vsf_mailtonamelength := vsf_mailtonamepos - vsf_mailtonamestartpos + 9 ;add the @vemma.com
				vsf_mailtonamestartpos := vsf_mailtonamestartpos + 2
				StringMid, vsf_mailtonameguess, A_LoopReadLine, vsf_mailtonamestartpos, vsf_mailtonamelength
				if vsf_mailtonameguess = %vsf_mailto%
					AddStatus(">> Email address is correct!")
				else
					AddStatus(">> Should be: " . vsf_mailtonameguess)
			}
		}
	}
	if !vsf_mailto
	{
		AddStatus(">> ERROR: Could not find a mailto: address.")
		return
	}
	if !vsf_mailtonameguess
	{
		AddStatus(">> ERROR: Could not guess name.")
		GuiControl,, vsf_mailtobox, %vsf_mailto%
	} else
		GuiControl,, vsf_mailtobox, %vsf_mailtonameguess%
	gosub, EnableSigEdit
return


vsf_updatesig:
	GuiControlGet, vsf_mailtobox
	StringCaseSense, On
	if vsf_mailtobox = ""
		return
	if vsf_mailtobox = %vsf_mailto%
		return
	AddStatus("Updating " . vsf_sigdropdown . ".htm...")
	FileCopy, %vsf_chosensig%, %vsf_chosensig%.VSF_%A_YYYY%%A_MMM%%A_DD%_%A_Hour%%A_Min%%A_Sec%
	if ErrorLevel
	{
		AddStatus(">> ERROR: Backup failed. Aborting.")
		return
	}
	FileRead, vsf_sig_htm, %vsf_chosensig%
	if ErrorLevel
	{
		AddStatus(">> ERROR: Could not load signature file.")
		return
	}
	StringReplace, vsf_sig_htm, vsf_sig_htm, %vsf_mailto%, %vsf_mailtobox%
	if ErrorLevel
	{
		AddStatus(">> ERROR: String replace failed.")
		return
	}
	FileDelete, %vsf_chosensig%
	FileAppend, %vsf_sig_htm%, %vsf_chosensig%
	AddStatus("> Updated!")
	
	AddStatus("Updating " . vsf_sigdropdown . ".rtf...")
	vsf_chosensig = %vsf_sigpath%\%vsf_sigdropdown%.rtf
	FileCopy, %vsf_chosensig%, %vsf_chosensig%.VSF_%A_YYYY%%A_MMM%%A_DD%_%A_Hour%%A_Min%%A_Sec%
	if ErrorLevel
	{
		AddStatus(">> ERROR: Backup failed. Aborting.")
		return
	}
	FileRead, vsf_sig_rtf, %vsf_chosensig%
	if ErrorLevel
	{
		AddStatus(">> ERROR: Could not load signature file.")
		return
	}
	StringReplace, vsf_sig_rtf, vsf_sig_rtf, %vsf_mailto%, %vsf_mailtobox%
	if ErrorLevel
	{
		AddStatus(">> ERROR: String replace failed.")
		return
	}
	FileDelete, %vsf_chosensig%
	FileAppend, %vsf_sig_rtf%, %vsf_chosensig%
	
	AddStatus("> Updated!")
	StringCaseSense, Off
	AddStatus(">> Changed: " . vsf_mailto . " --> " . vsf_mailtobox,2)
	SendMessage, 0x014E, -1, 0,, ahk_id %DDL_ID%
	GuiControl,, vsf_mailtobox,
	gosub, DisableSigEdit
	gosub, vsf_createlogfile
return

vsf_createlogfile:
	GuiControlGet, vsf_log
	vsf_log = --------------------`nLogged in as: %A_UserName%`nComputer name: %A_ComputerName% [%A_IPAddress1% / %A_IPAddress2% / %A_IPAddress3% / %A_IPAddress4%]`n--------------------`n%vsf_log%
	FileAppend, %vsf_log%, %vsf_sigpath%\VemmaSigFix.%A_YYYY%%A_MMM%%A_DD%_%A_Hour%%A_Min%%A_Sec%.log
	FileAppend, %vsf_log%, %A_WorkingDir%\%vsf_computername%.%A_YYYY%%A_MMM%%A_DD%_%A_Hour%%A_Min%%A_Sec%.log
return

DisableButtons:
	GuiControl, Disable, vsf_searchbutton
	GuiControl, Disable, vsf_nameinput
	GuiControl, Disable, vsf_sigtextlabel
	GuiControl, Disable, vsf_sigdropdown
	GuiControl, Disable, vsf_mailtobox
	GuiControl, Disable, vsf_updatebutton
return


EnableButtons:
	GuiControl, Enable, vsf_searchbutton
	GuiControl, Enable, vsf_nameinput
return

EnableSigChoice:
	GuiControl, Enable, vsf_sigtextlabel
	GuiControl, Enable, vsf_sigdropdown
return

DisableSigChoice:
	GuiControl, Disable, vsf_sigtextlabel
	GuiControl, Disable, vsf_sigdropdown
return

EnableSigEdit:
	GuiControl, Enable, vsf_mailtobox
	GuiControl, Enable, vsf_updatebutton
return

DisableSigEdit:
	GuiControl, Disable, vsf_mailtobox
	GuiControl, Disable, vsf_updatebutton
return


ClearVars:
	FileDelete, %A_Temp%\vsf*.*
	vsf_computername =
	vsf_detectfail =
	vsf_guesspath =
	vsf_guesspathpos =
	vsf_ip =
	vsf_loggedonnextline =
	vsf_mailto =
	vsf_mailtonameguess =
	vsf_profilelist =
	vsf_profiles =
	vsf_sigdropdown =
	vsf_siglist =
	vsf_sigpath =
	vsf_sigs =
	vsf_username =
	
	Loop, %vsf_allprofiles0%
		vsf_allprofiles%A_Index% =
	Loop, %vsf_pingresult0%
		vsf_pingresult%A_Index% =
	Loop, %vsf_profiles0%
		vsf_profiles%A_Index% =
	Loop, %vsf_profilelist0%
		vsf_profilelist%A_Index% =
	Loop, %vsf_psloggedon0%
		vsf_psloggedon%A_Index% =
	Loop, %vsf_sigs0%
		vsf_sigs%A_Index% =
	
	GuiControl,, vsf_sigdropdown, |
	GuiControl,, vsf_mailtobox,
return

Reset:
	GuiControl,, vsf_nameinput,
	GuiControl,, vsf_log,
	gosub, DisableSigEdit
	gosub, DisableSigChoice
return


Completed:
	gosub, EnableButtons
	;~ gosub, ClearVars
	vsf_notfirstrun = 1
	AddStatus("Search complete!",2)
return

;######################################
;######################################
;############## FUNCTIONS #############
;######################################
;######################################
AddStatus(TextToLog="", NewLines=1) {
	global Edit_ID
	NewLine =
	Loop %NewLines%
		NewLine := NewLine . "`r`n"
	SendMessage 0xB1, -1, -1, , ahk_id %Edit_ID% 
	Control, EditPaste, %TextToLog%%NewLine%, , ahk_id %Edit_ID%
}